// Copyright (c) 2022 Huawei Device Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SERVICES_DEVICE_GEOLOCATION_LOCATION_PROVIDER_OHOS_H_
#define SERVICES_DEVICE_GEOLOCATION_LOCATION_PROVIDER_OHOS_H_

#include <memory>

#include <location_adapter.h>
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "services/device/public/cpp/geolocation/location_provider.h"
#include "services/device/public/mojom/geoposition.mojom.h"

namespace device {
class LocationProviderCallback : public OHOS::NWeb::LocationCallbackAdapter {
 public:
  LocationProviderCallback() {}
  ~LocationProviderCallback() = default;

  enum LocationErrorCode {
    LOCATION_GET_SUCCESS = 0,
    LOCATION_GET_FAILED,
    LOCATION_UNKNOWN_ERROR,
  };

  typedef base::RepeatingCallback<void(const mojom::Geoposition&)>
      UpdateCallback;

  // ILocatorCallback implementation.
  void OnLocationReport(
      const std::unique_ptr<OHOS::NWeb::LocationInfo>& location) override;
  void OnLocatingStatusChange(const int status) override;
  void OnErrorReport(const int errorCode) override;

  void OnNewLocationAvailable(
      const std::unique_ptr<OHOS::NWeb::LocationInfo>& location);
  void OnNewErrorAvailable(std::string message);
  void SetUpdateCallback(const UpdateCallback& callback) {
    callback_ = callback;
  }
  const mojom::Geoposition& GetPosition() { return last_position_; }

 private:
  // Calls |callback_| with the new location.
  void NewGeopositionReport(const mojom::Geoposition& position);

  mojom::Geoposition last_position_;
  UpdateCallback callback_;
};

// Location provider for OpenHarmony using the platform provider over JNI.
class LocationProviderOhos : public LocationProvider {
 public:
  LocationProviderOhos();
  ~LocationProviderOhos() override;

  // LocationProvider implementation.
  void SetUpdateCallback(
      const LocationProviderUpdateCallback& callback) override;
  void StartProvider(bool high_accuracy) override;
  void StopProvider() override;
  const mojom::Geoposition& GetPosition() override;
  void OnPermissionGranted() override;

  void ProviderUpdateCallback(const mojom::Geoposition& position);

 private:
  void RequestLocationUpdate(bool high_accuracy);
  void CreateLocationManagerIfNeeded();
  void SetRequestConfig(
      std::unique_ptr<OHOS::NWeb::LocationRequestConfig>& requestConfig,
      bool high_accuracy);

  std::unique_ptr<OHOS::NWeb::LocationProxyAdapter> locator_;

  LocationProviderUpdateCallback callback_;

  bool is_running_ = false;
  std::shared_ptr<LocationProviderCallback> locator_callback_ = nullptr;
};

}  // namespace device

#endif  // SERVICES_DEVICE_GEOLOCATION_LOCATION_PROVIDER_OHOS_H_
